package criptosuma.formulation.constraints;

import java.util.ArrayList;
import java.util.List;
import criptosuma.formulation.variables.Carry;
import criptosuma.formulation.variables.Letter;

import es.deusto.ingenieria.is.csp.formulation.Constraint;
import es.deusto.ingenieria.is.csp.formulation.Variable;

public class SumConstraint extends Constraint<Integer> 
{
	private List<Variable<Integer>> left = null;
	private List<Variable<Integer>> right = null;
	
	public SumConstraint(String name, List<Variable<Integer>> operandos, List<Variable<Integer>> rdo)
	{
		super(name, operandos);
		this.addVariables((ArrayList<Variable<Integer>>) rdo);
		this.left = operandos;
		this.right = rdo;
	}
	
	@Override
	public boolean isSatisfied(Variable<Integer> variable, Integer valor) 
	{
		/*
		 * Calculamos por separado las sumas parciales: 
		 * Left (operandos + Carry anterior)
		 * Right (resultado + Carry actual)
		 * Si la sumaL = sumaR entonces true.
		 */
		List<Variable<Integer>> tempL = new ArrayList<Variable<Integer>>(left);
		List<Variable<Integer>> tempR = new ArrayList<Variable<Integer>>(right);
		int sumL = 0;
		int sumR = 0;

		for (int i = 0; i < tempL.size(); i++) 
		{
			if(!variable.equals(tempL.get(i)) && !tempL.get(i).hasValue())
			{
				return true;
			}
			else if(tempL.get(i).equals(variable))
			{
				sumL += valor;
			}
			else if(tempL.get(i).hasValue())
			{
				sumL += tempL.get(i).getValue();
			}
		}
		
		for (int i = 0; i < tempR.size(); i++) 
		{
			if(!variable.equals(tempR.get(i)) && !tempR.get(i).hasValue())
			{
				return true;
			}
			else if(tempR.get(i).equals(variable))
			{
				if(tempR.get(i) instanceof Carry)
				{
					sumR+= valor*10;
				}
				else if(tempR.get(i) instanceof Letter)
				{
					sumR+= valor;
				}
			}
			else if(tempR.get(i).hasValue())
			{
				if(tempR.get(i) instanceof Carry)
				{
					sumR+= tempR.get(i).getValue()*10;
				}
				else if(tempR.get(i) instanceof Letter)
				{
					sumR+= tempR.get(i).getValue();
				}
			}
		}
		return (sumL == sumR);
	}
	
	@Override
	public String toString()
	{
		String n = "";
		for (int i = 0; i < left.size(); i++) 
		{
			n += left.get(i).getName() + "(" + left.get(i).getValue() + ")";
			if(i == left.size()-1)
			{
				n += " = ";
			}
			else
				n += " + ";
		}
		
		System.out.println("Right: " + right);
		
		for(int i = 0; i < right.size(); i++) 
		{
			n += right.get(i).getName() + "(" + right.get(i).getValue() + ")";
			if(i == right.size()-1)
			{
				n += ". ";
			}
			else
				n += " + ";
		}
		return n;
	}
	
	public void addRight(Variable<Integer> variable)
	{
		this.right.add(variable);
	}
	
	public void addLeft(Variable<Integer> variable)
	{
		this.left.add(variable);
	}

	public List<Variable<Integer>> getLeft() {
		return left;
	}

	public void setLeft(List<Variable<Integer>> left) {
		this.left = left;
	}

	public List<Variable<Integer>> getRight() {
		return right;
	}

	public void setRight(List<Variable<Integer>> right) {
		this.right = right;
	}
	
	public void addLeftRightToVariables()
	{
		this.addVariables((ArrayList<Variable<Integer>>) left);
		this.addVariables((ArrayList<Variable<Integer>>) right);
	}
}



